package com.base.common.util.file;

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;

import com.base.common.util.StringHandler;
import com.base.common.util.StringUtils;
import com.base.common.util.date.DateUtil;
import com.base.common.util.log.LogUtil;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class FileUtil {

    /**
     * 在SD卡上创建文件
     * 
     * @throws IOException
     */
    public static File creatSDFile(String fileName) {
        File file = new File(fileName);
        try {
            file.createNewFile();
        } catch (IOException e) {
        }
        return file;
    }



    /**
     * 在SD卡上创建目录
     * 
     * @param dirName
     */
    public static File creatSDDir(String dirName) {
        File dir = new File(dirName);
        dir.mkdirs();
        return dir;
    }

    /**
     * 判断SD卡上的文件夹是否存在
     */
    public static boolean isFileExist(String fileName) {

        try {
            File file = new File(fileName);
            return file.exists();
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 网络文件转化输入流
     * 
     * @param path
     * @return
     * @throws Exception
     */
    public static InputStream getRequest(String path) throws Exception {
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5000); // 5秒
        if (conn.getResponseCode() == 200) {
            return conn.getInputStream();
        }
        return null;
    }

    /**
     * 把输入流转化为二进制流
     * 
     * @param inStream
     * @return
     * @throws Exception
     */
    public static byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[4096];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        outSteam.close();
        inStream.close();
        return outSteam.toByteArray();
    }

    /**
     * 将一个InputStream里面的数据写入到SD卡中
     */
    public static File saveFile(File file, Bitmap photo) {

        FileOutputStream fOut = null;
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            fOut = new FileOutputStream(file);
        } catch (Exception e) {
            e.printStackTrace();
        }

        photo.compress(Bitmap.CompressFormat.JPEG, 100, fOut);// 把Bitmap对象解析成流

        try {
            fOut.flush();
            fOut.close();
        } catch (Exception e) {

        }

        return file;
    }

    public static String getSizeName(long size) {
        DecimalFormat format = new DecimalFormat("0.00");

        if (size < 1024) {
            return size + "B";
        } else if (size >= 1024 && size < 1024 * 1024) {
            return format.format((double) size / 1024l) + "KB";
        } else {
            return format.format((double) size / 1024l / 1024l) + "M";

        }
    }

    /**
     * 打开文件
     * 
     * @param context
     * @param file
     * @param type
     */
    public static void openFile(Context context, File file, String type) {
        // Uri uri = Uri.parse("file://"+file.getAbsolutePath());
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        // 设置intent的Action属性
        intent.setAction(Intent.ACTION_VIEW);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        // 获取文件file的MIME类型
        if (type == null)
            type = getMIMEType(file);
        LogUtil.i(TAG, "type:" + type);
        // 设置intent的data和Type属性。
        intent.setDataAndType(Uri.fromFile(file), type);
        try {
            // 跳转
            context.startActivity(intent);
        } catch (ActivityNotFoundException ex) {
            LogUtil.e(TAG, StringUtils.getExceptionMsg(ex));
        }
    }

    public static final String TAG = "FileUtil";

    public static String getMIMEType(File file) {
        String type = "*/*";
        String fName = file.getName();
        // 获取后缀名前的分隔符"."在fName中的位置。
        int dotIndex = fName.lastIndexOf(".");
        if (dotIndex < 0) {
            return type;
        }
        /* 获取文件的后缀名 */
        String end = fName.substring(dotIndex, fName.length()).toLowerCase();
        if (end == "")
            return type;
        // 在MIME和文件类型的匹配表中找到对应的MIME类型。
        for (int i = 0; i < MIME_MAPTABLE.length; i++) {
            if (end.equals(MIME_MAPTABLE[i][0]))
                type = MIME_MAPTABLE[i][1];
        }
        return type;
    }

    // 建立一个MIME类型与文件后缀名的匹配表
    public static final String[][] MIME_MAPTABLE = {
            // {后缀名， MIME类型}
            { ".3gp", "video/3gpp" },
            { ".apk", "application/vnd.android.package-archive" },
            { ".asf", "video/x-ms-asf" }, { ".avi", "video/x-msvideo" },
            { ".bin", "application/octet-stream" }, { ".bmp", "image/bmp" },
            { ".c", "text/plain" }, { ".class", "application/octet-stream" },
            { ".conf", "text/plain" }, { ".cpp", "text/plain" },
            { ".doc", "application/msword" },
            { ".exe", "application/octet-stream" }, { ".gif", "image/gif" },
            { ".gtar", "application/x-gtar" }, { ".gz", "application/x-gzip" },
            { ".h", "text/plain" }, { ".htm", "text/html" },
            { ".html", "text/html" }, { ".jar", "application/java-archive" },
            { ".java", "text/plain" }, { ".jpeg", "image/jpeg" },
            { ".jpg", "image/jpeg" }, { ".js", "application/x-javascript" },
            { ".log", "text/plain" }, { ".m3u", "audio/x-mpegurl" },
            { ".m4a", "audio/mp4a-latm" }, { ".m4b", "audio/mp4a-latm" },
            { ".m4p", "audio/mp4a-latm" }, { ".m4u", "video/vnd.mpegurl" },
            { ".m4v", "video/x-m4v" }, { ".mov", "video/quicktime" },
            { ".mp2", "audio/x-mpeg" }, { ".mp3", "audio/x-mpeg" },
            { ".mp4", "video/mp4" },
            { ".mpc", "application/vnd.mpohun.certificate" },
            { ".mpe", "video/mpeg" }, { ".mpeg", "video/mpeg" },
            { ".mpg", "video/mpeg" }, { ".mpg4", "video/mp4" },
            { ".mpga", "audio/mpeg" },
            { ".msg", "application/vnd.ms-outlook" }, { ".ogg", "audio/ogg" },
            { ".pdf", "application/pdf" }, { ".png", "image/png" },
            { ".pps", "application/vnd.ms-powerpoint" },
            { ".ppt", "application/vnd.ms-powerpoint" },
            { ".prop", "text/plain" },
            { ".rar", "application/x-rar-compressed" },
            { ".rc", "text/plain" }, { ".rmvb", "audio/x-pn-realaudio" },
            { ".rtf", "application/rtf" }, { ".sh", "text/plain" },
            { ".tar", "application/x-tar" },
            { ".tgz", "application/x-compressed" }, { ".txt", "text/plain" },
            { ".wav", "audio/x-wav" },
            { ".wma", "audio/x-ms-wma" },
            { ".wmv", "audio/x-ms-wmv" },
            { ".wps", "application/vnd.ms-works" },
            // {".xml", "text/xml"},
            { ".xml", "text/plain" }, { ".z", "application/x-compress" },
            { ".zip", "application/zip" },
            { ".xls", "application/vnd.ms-excel" } };

    /**
     * 删除文件
     * 
     * @param filePathAndName
     * @return
     */
    public static boolean delFile(String... filePathAndName) {
        boolean isDel = false;
        try {
            for (int i = 0; i < filePathAndName.length; i++) {
                String filePath = filePathAndName[i];
                File myDelFile = new File(filePath);
                if (myDelFile.exists()) {
                    isDel = myDelFile.delete();
                }
            }
        } catch (Exception e) {
            isDel = false;
        }
        return isDel;
    }

    /**
     * 拷贝assets文件到存储器上
     * 
     * @param context
     * @param assetFileName
     * @param destFileDir
     * @return
     */
    public static boolean copyApkFromAssets(Context context,
            String assetFileName, String destFileDir) {
        boolean copyIsFinish = false;
        try {
            InputStream is = context.getAssets().open(assetFileName);
            writeToSdcard(is, destFileDir, assetFileName);
            copyIsFinish = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return copyIsFinish;
    }

    /**
     * 写文件到存储器上
     * 
     * @param input
     * @param fileDir
     * @param fileName
     */
    public static void writeToSdcard(InputStream input, String fileDir,
            String fileName) {
        File file = null;
        OutputStream output = null;
        try {
            File fileDirs = new File(fileDir);
            if (!fileDirs.exists()) {
                fileDirs.mkdir();
            }
            file = new File(fileDirs.toString() + File.separator + fileName);
            if (!file.exists()) {
                file.createNewFile();
            }
            output = new FileOutputStream(file);
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = input.read(buffer)) > 0) {
                output.write(buffer, 0, len);
            }
            output.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (output != null) {
                    output.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static String getPrintSize(long size) {
        // 如果字节数少于1024，则直接以B为单位，否则先除于1024，后3位因太少无意义
        if (size < 1024) {
            return String.valueOf(size) + "B";
        } else {
            size = size / 1024;
        }
        // 如果原字节数除于1024之后，少于1024，则可以直接以KB作为单位
        // 因为还没有到达要使用另一个单位的时候
        // 接下去以此类推
        if (size < 1024) {
            return String.valueOf(size) + "KB";
        } else {
            size = size / 1024;
        }
        if (size < 1024) {
            // 因为如果以MB为单位的话，要保留最后1位小数，
            // 因此，把此数乘以100之后再取余
            size = size * 100;
            return String.valueOf((size / 100)) + "." + String.valueOf((size % 100)) + "MB";
        } else {
            // 否则如果要以GB为单位的，先除于1024再作同样的处理
            size = size * 100 / 1024;
            return String.valueOf((size / 100)) + "." + String.valueOf((size % 100)) + "GB";
        }
    }

    public static String getFileLastModifiedTime(File file, String format) {
        if(!StringHandler.isValidStr(format)){
            format = DateUtil.Date_Time_Format;
        }
        Calendar cal = Calendar.getInstance();
        long time = file.lastModified();
        SimpleDateFormat formatter = new SimpleDateFormat(format);
        cal.setTimeInMillis(time);

        // 输出：修改时间[2] 2009-08-17 10:32:38
        return formatter.format(cal.getTime());
    }


    /**
     * 获取文件的MD5值
     * @param filePath
     * @return
     */
    public static String getFileMD5(String filePath){
        File file = new File(filePath);
        return getFileMD5(file);
    }

    public static String getFileMD5(File file) {
        if (!file.isFile()) {
            return null;
        }
        MessageDigest digest = null;
        FileInputStream in = null;
        byte buffer[] = new byte[1024];
        int len;
        try {
            digest = MessageDigest.getInstance("MD5");
            in = new FileInputStream(file);
            while ((len = in.read(buffer, 0, 1024)) != -1) {
                digest.update(buffer, 0, len);
            }

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }finally {
            if(null != in){
                try {
                    in.close();
                    in = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return bytesToHexString(digest.digest());
    }

    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

}